/* 报告操作 */
const shell = require('shelljs');
const CONSTS = require('@lib/consts/index');
const Fs = require('@lib/utils/fs');
const {
  isValuableArray
} = require('@lib/utils/tools');
class Report {
  /**
   * 将性能报告需要的数据格式化，然后push到数组中，后续再统一写入报告文件中
   * @param {*} appendList 需要追加的数据
   * @param {*} title 问题标题
   * @param {*} outputList 最终输出到文件中的数据
   */
  static formatAndpushReportData(appendList, title, outputList) {
    const reportItems = appendList.map((item) => {
      const ret = {};
      Object.keys(item).forEach(key => {
        ret[CONSTS.FORMAT_REPORT_DATA_MAP[key]] = item[key];
      });
      return ret;
    });
    outputList.push({
      title,
      data: reportItems
    });
  }

  /**
   * json转换成html字符串
   * @param {*} jsonData json数据
   * @param {*} headTagIndex head标题标签的序号，从2开始，最大是6
   * @param {*} h2Index h2标签标题的序号
   * @returns html字符串
   */
  static json2Html(jsonData, headTagIndex = 2, h2Index) {
    let html = '';
    if (jsonData.title && headTagIndex === 2) {
      // 最外层的title 且是 h2标题，打上序号
      html += `<h${headTagIndex}>${h2Index + 1}、${jsonData.title}</h${headTagIndex}>`;
    } else {
      html += `<h${headTagIndex}>${jsonData.title}</h${headTagIndex}>`;
    }
    if (isValuableArray(jsonData.data)) {
      jsonData.data.forEach((item, index) => {
        if (item.title) {
          // 子项存在title，则需要设置h标签且递归调用json2Html
          const newHeadTagIndex = headTagIndex + 1 > 6 ? 6 : headTagIndex + 1;
          html += Report.json2Html(item, newHeadTagIndex, h2Index);
        } else {
          // 子项不存在title则直接展示p标签
          html += `<p><em>${index + 1})</em>`;
          Object.keys(item).forEach(key => {
            html += `\t<b>${key}</b>：${item[key]}`;
          });
          html += '</p>';
        }
      });
    }
    return html;
  }

  /**
   * 性能问题输出到临时文件中
   * @param {*} list 性能问题数据
   * @param {*} title 性能问题标题
   * @param {*} fileName 文件名称
   * @param {*} cb 回调函数
   */
  static outputTempFile(list, title, fileName, cb = null) {
    const jsonData = JSON.stringify({
      title,
      data: list
    });
    Fs.appendData2File(
      CONSTS.REPORT_OUTPUT_DIR,
      fileName,
      jsonData,
      (filePath) => {
        cb && cb();
      }
    );
  }

  /**
   * 生成html报告
   * @param {*} title 报告标题
   * @param {*} htmlData 报告内容
   * @param {*} cb 回调函数
   */
  static genHtmlReport(title, htmlData, cb = null) {
    // 1. HTML 模板内容
    const tpl = CONSTS.TPL_HTML_CONTENT;
    // 2.将 HTML 内容插入模板中
    const resultHtml = tpl
      .replace('<!-- TITLE_PLACEHOLDER -->', title)
      .replace('<!-- CONTENT_PLACEHOLDER -->', htmlData);
    // 3.HTML文件内容写入报告文件
    Fs.appendData2File(
      CONSTS.REPORT_OUTPUT_DIR,
      CONSTS.REPORT_FINAL_FILENAME,
      resultHtml,
      (filePath) => {
        cb && cb(filePath);
      }
    );
  }

  /**
   * 使用默认浏览器打开html文件
   * @param {*} filePath 文件路径
   */
  static openInBrowser(filePath) {
    shell.exec(`start ${filePath}`);
    console.log(`使用浏览器打开${filePath}文件`);
  }

  /**
   * 生成并展示html格式的报告
   * @param {*} title 报告标题
   * @param {*} cb 回调函数
   */
  static showReport(title, cb = null) {
    // 1.遍历报告目录下的所有文件
    const fileList = [];
    Fs.traverseDirectory(CONSTS.REPORT_OUTPUT_DIR, fileList);
    // 报告标题对应h1标签
    let htmlData = `<h1>${title}</h1>`;
    fileList.forEach((tempFile, index) => {
      if (tempFile.ext === '.json') {
        // 2.读取json文件内容
        const jsonDataStr = Fs.readFileSync(tempFile.filePath);
        // 3.json转换成html字符串
        const jsonData = JSON.parse(jsonDataStr);
        htmlData += Report.json2Html(jsonData, 2, index);
      }
    });
    // 4.生成html报告
    Report.genHtmlReport(title, htmlData, (filePath) => {
      // 5.使用默认浏览器打开报告
      Report.openInBrowser(filePath);
      cb && cb();
    });
  }
}

module.exports = Report;
